package gipfProject.games.zertz.gui;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import gipfProject.tools.ResourceLoader;

import javax.swing.JPanel;

import gipfProject.games.zertz.data.PieceData;
import gipfProject.games.zertz.data.ZertzData;
import gipfProject.games.zertz.engine.ZertzEngine;

public class BoardUI extends JPanel implements MouseListener {

	ResourceLoader images;
	ZertzData gameState;
	ZertzEngine engine;
	ZertzUI gui;

	static final int colSize = 40, rowSize = 20, xOffset = 10, yOffset = 10, tileSize = 32;

	BoardUI(ResourceLoader images, ZertzData gameState, ZertzEngine engine,
			ZertzUI gui) {
		this.images = images;
		this.gameState = gameState;
		this.engine = engine;
		this.gui = gui;
		addMouseListener(this);
	}

	public void paintComponent(Graphics g) {
		// Draw a border around the board
		g.setColor(Color.black);
		g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);
		g.drawRect(1, 1, getSize().width - 3, getSize().height - 3);

		// Fill the center of the board
		g.setColor(Color.blue);
		g.fillRect(2, 2, getSize().width - 4, getSize().height - 4);

		// For each tile on the board
		for (int col = 0; col < gameState.boardCols; col++) {
			for (int row = 0; row < gameState.boardRows; row++) {

				// Get the piece at that spot
				PieceData piece = gameState.board[col][row];

				// If this is a valid piece, draw it
				if (piece.isValid()) {
					drawPiece(g, col, row, piece);
				}
			}
		}

	}// End of paint

	public void drawPiece(Graphics g, int col, int row, PieceData piece) {
		Image pieceImage = images.getResource("ZertzRing");
		g.drawImage(pieceImage, xOffset + col * colSize, yOffset + row
				* rowSize, this);

		String imageFile = piece.imageFile();

		if (imageFile != null) {
			Image marbleImage = images.getResource(imageFile);
			g.drawImage(marbleImage, 9 + xOffset + col * colSize, 9 + yOffset
					+ row * rowSize, this);
		}
		
		// If we are highlighting captures, check if this should be highlighted
		if (gameState.moveType == ZertzData.captureMarble && gameState.getSelectedPiece() == null){
			if (gameState.canPieceCapture(col,row)){
				showGreenHighlight(g,col,row);
			}
		}
		
		//If we already have a piece selected, highlight the potential moves
		if (gameState.moveType == ZertzData.captureMarble && gameState.getSelectedPiece() != null){
			if (gameState.canCompleteCapture(col,row)){
				showGreenHighlight(g,col,row);
			}
		}		
		
		// If this is a highlighted piece, highlight it
		if (piece.isHighlighted()){
			showYellowHighlight(g,col,row);
		}
	}// End drawPiece

	private void showYellowHighlight(Graphics g, int col, int row){
		g.setColor(new Color((float)1,(float)0,(float)1,(float)0.3));
		g.fillRect(0 + xOffset + col * colSize,
				0 + yOffset + row * rowSize,
				tileSize,tileSize);
		
		g.setColor(Color.yellow);
		g.drawRect(0 + xOffset + col * colSize,
				0 + yOffset + row * rowSize,
				tileSize,tileSize);
		g.drawRect(-1 + xOffset + col * colSize,
				-1 + yOffset + row * rowSize,
				tileSize+2,tileSize+2);	
	}
	
	private void showGreenHighlight(Graphics g, int col, int row){
		g.setColor(new Color((float)0,(float)1,(float)0,(float)0.3));
		g.fillRect(0 + xOffset + col * colSize,
				0 + yOffset + row * rowSize,
				tileSize,tileSize);
		
		g.setColor(new Color((float)0,(float)1,(float)0,(float)0.6));
		g.drawRect(0 + xOffset + col * colSize,
				0 + yOffset + row * rowSize,
				tileSize,tileSize);
		g.drawRect(-1 + xOffset + col * colSize,
				-1 + yOffset + row * rowSize,
				tileSize+2,tileSize+2);
	}
	
	private void handleClick(int col, int row) {
		gameState.clearErrorMessage();
		engine.clickTile(col, row);
		gui.refreshDisplay();
	}

	public void mousePressed(MouseEvent e) {
		// Adjust the coordinates to match the board's grid
		int col = (e.getX() - xOffset) / colSize;
		int row = (e.getY() - yOffset - 15) / rowSize; // FIXME: Magic Number

		// If this is a skipped/offset tile, adjust to a real tile
		if (row % 2 == col % 2) {
			row++;
		}

		// If the result is within the bounds of the board, process the click
		if (col >= 0 && col < gameState.boardCols && row >= 0
				&& row < gameState.boardRows) {
			handleClick(col, row);
		}

		// "Consume" the event so it won't be processed in the
		// default manner by the source which generated it.
		e.consume();
	}// End mosePressed

	// These functions do not get used
	public void mouseClicked(MouseEvent e) {
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mouseReleased(MouseEvent e) {
	}

}
